<template>
	<view class="bt-container" :style="[containerStyle]">
		<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
		<view class="mainContent" data-type="image" @touchstart="wxsModule.touchStart" @touchmove="wxsModule.touchMove" @touchend="wxsModule.touchEnd">
		<!-- #endif -->
		<!-- #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
		<view class="mainContent" data-type="image" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd">
		<!-- #endif -->
			<template v-if="imageRect && cropperRect">
				<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
				<image mode="aspectFit" :src="imageSrc" class="image" :rotateAngle="rotateAngle" :change:rotateAngle="wxsModule.changeRotateAngle" :change:imageRect="wxsModule.changeImageRect" :imageRect="imageRect" :class="{ anim }">
				<!-- #endif -->
				<!-- #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
				<image mode="aspectFit" :src="imageSrc" class="image" :style="[imageStyle]" :class="{ anim }">
				<!-- #endif -->
				</image>
				<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
				<view class="cropper" :class="{ anim }" :change:cropperRect="wxsModule.changeCropper" :cropperRect="cropperRect" :change:ratio="wxsModule.changeRatio" :ratio="ratio" >
				<!-- #endif -->
				<!-- #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
				<view class="cropper" :class="{ anim }"  :style="[cropperStyle]">
				<!-- #endif -->
					<image class="mask" :src="mask"></image>
					<template v-if="showGrid">
						<view class="line row row1"></view>
						<view class="line row row2"></view>
						<view class="line col col1"></view>
						<view class="line col col2"></view>
					</template>
					<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5  -->
					<view class="controller vertical left" @touchstart="wxsModule.touchStart" data-type="controller" />
					<view class="controller vertical right" @touchstart="wxsModule.touchStart" data-type="controller" />
					<view class="controller horizon top" @touchstart="wxsModule.touchStart" data-type="controller" />
					<view class="controller horizon bottom" @touchstart="wxsModule.touchStart" data-type="controller" />
					<view class="controller left top" @touchstart="wxsModule.touchStart" data-type="controller" />
					<view class="controller left bottom" @touchstart="wxsModule.touchStart" data-type="controller" />
					<view class="controller right top" @touchstart="wxsModule.touchStart" data-type="controller" />
					<view class="controller right bottom" @touchstart="wxsModule.touchStart" data-type="controller" />
					<!-- #endif -->
					<!-- #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5  -->
					<view class="controller vertical left" @touchstart.stop="touchStart(-1, 0, $event)" />
					<view class="controller vertical right" @touchstart.stop="touchStart(1, 0, $event)" />
					<view class="controller horizon top" @touchstart.stop="touchStart(0, -1, $event)" />
					<view class="controller horizon bottom" @touchstart.stop="touchStart(0, 1, $event)" />
					<view class="controller left top" @touchstart.stop="touchStart(-1, -1, $event)" />
					<view class="controller left bottom" @touchstart.stop="touchStart(-1, 1, $event)" />
					<view class="controller right top" @touchstart.stop="touchStart(1, -1, $event)" />
					<view class="controller right bottom" @touchstart.stop="touchStart(1, 1, $event)" />
					<!-- #endif -->
				</view>
			</template>
		</view>
			<canvas v-if="type2d" type="2d" class="bt-canvas" :width="target.width" :height="target.height"></canvas>
			<canvas
				v-else
				:canvas-id="canvasId"
				class="bt-canvas"
				:style="{
					width: target.width + 'px',
					height: target.height + 'px'
				}"
				:width="target.width * pixel"
				:height="target.height * pixel"
			></canvas>
	</view>
</template>

<script>
// #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
import touches from './js/touchs.js';
// #endif
import { parseUnit,sleep } from './utils/tools.js';
/**
 * better-cropper 图片裁切插件
 */
export default {
	name: 'bt-cropper',
	props: {
		// 图片路径，支持网络路径和本地路径
		imageSrc: {
			type: String,
			default: '',
			required: true
		},
		mask: {
			type: String,
			default: ''
		},
		// 手动指定容器的大小
		containerSize: {
			type: Object,
			default: null
		},
		// 输出图片的格式，默认jpg
		fileType: {
			type: String,
			default: 'png'
		},
		// 生成的图片的宽度,不传或者传0表示按照原始分辨率裁切
		dWidth: Number,
		maxWidth: {
			type: Number,
			default: 2000
		},
		// 裁切比例，0表示自由
		ratio: {
			type: Number,
			default: 0,
			validator(value) {
				if (typeof value === 'number') {
					if (value < 0) {
						return false;
					}
				} else {
					return false;
				}
				return true;
			}
		},
		// 旋转角度
		rotate: Number,
		// 是否展示网格
		showGrid: {
			type: Boolean,
			default: false
		},
		// 图片质量，0-1 越大质量越好
		quality: {
			type: Number,
			default: 1
		},
		canvas2d: {
			type: Boolean,
			default: false
		},
		// 初始的图片位置
		initPosition: {
			type: Object,
			default() {
				return null;
			}
		},
		// 是否开启操作结束后自动放大
		autoZoom: {
			type: Boolean,
			default: true
		}
	},
	// #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
	mixins: [touches],
	// #endif
	data() {
		return {
			canvasId: 'bt-cropper',
			containerRect: null,
			imageInfo: null,
			operationHistory: [],
			operationIndex: 0,
			anim: false,
			timer: null,
			// 是否使用2D canvas
			type2d: false,
			pixel: 1,
			imageRect: null,
			cropperRect: null,
			target:{
				width:0,
				height:0
			}
		};
	},
	watch: {
		imageSrc: {
			handler(src) {
				if (typeof src === 'string' && src !== '') {
					this.imageInit(src);
				} else {
					this.imageInfo = null;
				}
			},
			immediate: true
		},
		ratio() {
			if (this.ratio != 0) {
				this.startAnim();
				this.init();
			}
		}
	},
	computed: {
		containerStyle() {
			if (this.containerSize && this.containerRect) {
				return {
					width: this.containerRect.width + 'px',
					height: this.containerRect.height + 'px'
				};
			}
			return {};
		},
		rotateAngle(){
			const angel = Number(this.rotate)
			if(isNaN(angel)){
				return 0
			}else{
				return angel % 360
			}
		}
	},
	methods: {
		startAnim() {
			this.stopAnim();
			this.anim = true;
			this.timer = setTimeout(() => {
				this.anim = false;
			}, 200);
		},
		stopAnim() {
			this.anim = false;
			clearTimeout(this.timer);
		},
		imageInit(src) {
			uni.showLoading({
				title: '载入中...'
			});
			uni.getImageInfo({
				src,
				success: res => {
					this.imageInfo = res;
					this.$nextTick(() => {
						this.getContainer().then(rect => {
							this.containerRect = rect;
							this.init();
						});
					});
				},
				fail: (err) => {
					this.$emit('loadFail',err);
					uni.showToast({
						title: '图片下载失败!',
						icon: 'none'
					});
				},
				complete(res) {
					uni.hideLoading();
				}
			});
		},
		initCropper() {
			const imageRate = this.imageInfo.width / this.imageInfo.height;
			const containerRate = this.containerRect.width / this.containerRect.height;
			const imageRect = {};
			let cropperRate = this.ratio;
			if (cropperRate == 0) {
				if (this.cropperRect) {
					cropperRate = this.cropperRect.width / this.cropperRect.height;
				} else {
					cropperRate = 1;
				}
			}
			const cropperRect = {};
			if (containerRate > cropperRate) {
				cropperRect.height = this.containerRect.height * 0.85;
				cropperRect.width = cropperRect.height * cropperRate;
			} else {
				cropperRect.width = this.containerRect.width * 0.85;
				cropperRect.height = cropperRect.width / cropperRate;
			}
			if (cropperRate > imageRate) {
				imageRect.width = cropperRect.width;
				imageRect.height = imageRect.width / imageRate;
			} else {
				imageRect.height = cropperRect.height;
				imageRect.width = imageRect.height * imageRate;
			}
			imageRect.left = (this.containerRect.width - imageRect.width) / 2;
			imageRect.top = (this.containerRect.height - imageRect.height) / 2;
			cropperRect.left = imageRect.left + (imageRect.width - cropperRect.width) / 2;
			cropperRect.top = imageRect.top + (imageRect.height - cropperRect.height) / 2;
			return {
				imageRect,
				cropperRect
			};
		},
		init() {
			const {imageRect,cropperRect} = this.initCropper()
			if(this.initPosition){
				const scale = this.imageInfo.width/imageRect.width;
				const {left,top,width,height} = this.initPosition;
				if(left!==undefined&&top!==undefined&&width!==undefined&&height!==undefined){
					cropperRect.width = width/scale;
					cropperRect.height = height/scale;
					cropperRect.left = left/scale;
					cropperRect.top = top/scale;
					this.$nextTick(this.zoomToFill);
				}
			}
			this.imageRect = imageRect
			this.cropperRect = cropperRect
			this.operationHistory = [{imageRect,cropperRect}];
			this.operationIndex = 0;
			this.setTarget();
			// #ifdef MP-WEIXIN
			const systemInfo = uni.getSystemInfoSync();
			if (this.canvas2d === false || systemInfo.platform === 'windows' || systemInfo.platform === 'mac') {
				this.type2d = false;
			} else {
				this.type2d = true;
				this.pixel = systemInfo.pixelRatio;
			}
			// #endif
			//非微信小程序端强制关闭canvas2d模式
			// #ifndef MP-WEIXIN
			this.type2d = false;
			// #endif
			// #ifdef  MP-TOUTIAO || MP-LARK || MP-ALIPAY
			this.type2d = this.canvas2d;
			// #endif
		},
		// 设置目标图像的大小
		setTarget(){
			const ratio = this.cropperRect.width / this.cropperRect.height;
			if (this.dWidth) {
				this.target = {
					width: this.dWidth,
					height: this.dWidth / (ratio || 1)
				}
			} else {
				const width = Math.min(this.maxWidth, this.cropperRect.width * (this.imageInfo.width / this.imageRect.width));
				this.target = {
					width,
					height: width / (ratio || 1)
				}
			}
		},
		addHistory({imageRect,cropperRect}){
			if(this.operationIndex!==this.operationHistory.length-1){
				this.operationHistory = this.operationHistory.slice(0,this.operationIndex)
			}
			this.operationHistory.push({
				imageRect,
				cropperRect
			});
			if (this.operationHistory.length > 10) {
				this.operationHistory.shift();
			}
			this.operationIndex = this.operationHistory.length - 1;
		},
		updateData(data) {
			this.imageRect = data.imageRect
			this.cropperRect = data.cropperRect
			this.addHistory(data);
			this.setTarget();
			if (this.autoZoom) {
				this.timer = setTimeout(() => {
					this.zoomToFill();
				}, 600);
			}
			const {imageRect,cropperRect} = data
			const scale = imageRect.width/this.imageInfo.width
			this.$emit('change', {
				left: (cropperRect.left - imageRect.left) /scale,
				top: (cropperRect.top - imageRect.top) / scale,
				width: cropperRect.width / scale,
				height: cropperRect.height / scale
			});
		},
		getContainer() {
			if (this.containerSize !== null && typeof this.containerSize == 'object') {
				const { width, height } = this.containerSize;
				return Promise.resolve({
					width: parseUnit(width),
					height: parseUnit(height)
				});
			} else {
				return new Promise(resolve => {
					const query = uni.createSelectorQuery().in(this);
					query
						.select('.mainContent')
						.boundingClientRect(rect => {
							resolve(rect);
						})
						.exec();
				});
			}
		},
		zoomToFill() {
			this.startAnim();
			const beforeCropper = {
				...this.cropperRect
			};
			const operation = {
				imageRect:this.imageRect,
				cropperRect:this.cropperRect
			};
			this.cropperRect = this.initCropper().cropperRect;
			const scale = this.cropperRect.width / beforeCropper.width;
			const ox = beforeCropper.left - this.imageRect.left;
			const oy = beforeCropper.top - this.imageRect.top;
			this.imageRect = {
				width: this.imageRect.width * scale,
				height: this.imageRect.height * scale,
				left: this.imageRect.left + (this.cropperRect.left - beforeCropper.left) - (scale - 1) * ox,
				top: this.imageRect.top + (this.cropperRect.top - beforeCropper.top) - (scale - 1) * oy
			};
		},
		onTouchStart() {
			this.stopAnim();
		},
		// 撤销
		undo() {
			if (this.operationIndex > 0) {
				this.operationIndex--;
				this.imageRect = this.operationHistory[this.operationIndex].imageRect;
				this.cropperRect = this.operationHistory[this.operationIndex].cropperRect;
				return true;
			}
			return false;
		},
		// 重做
		resume() {
			if (this.operationIndex < this.operationHistory.length - 1) {
				this.operationIndex++;
				this.imageRect = this.operationHistory[this.operationIndex].imageRect;
				this.cropperRect = this.operationHistory[this.operationIndex].cropperRect;
				return true;
			}
			return false;
		},
		async drawImage(ctx,image,x,y,w,h){
			if (this.type2d) {
				await new Promise(resolve => (image.onload = resolve));
				ctx.drawImage(image, x * this.pixel, y * this.pixel, w * this.pixel, h * this.pixel);
			} else {
				const path = await new Promise((resolve)=>{
					uni.getImageInfo({
						src:image,
						success({path}){
							resolve(path)
						}
					})
				})
				ctx.drawImage(path, x * this.pixel, y * this.pixel, w * this.pixel, h * this.pixel);
				await new Promise((resolve) => ctx.draw(false,resolve));
			}
		},
		/**
		 * 异步裁剪图片的方法
		 *
		 * @returns 返回一个 Promise，在成功时返回裁剪后的图片路径，失败时返回错误信息
		 */
		async crop() {
			let ctx;
			let canvas;
			this.$emit('cropStart')
			this.setTarget()
			if (this.type2d) {
				const query = uni.createSelectorQuery().in(this);
				canvas = await new Promise(resolve =>
					query
						.select('.bt-canvas')
						.node(({ node }) => resolve(node))
						.exec()
				);
				canvas.width = this.target.width * this.pixel;
				canvas.height = this.target.height * this.pixel;
				ctx = canvas.getContext('2d');
				// #ifdef MP-TOUTIAO
				if(this.type2d){
					console.warn("请注意：目前头条系小程序暂时无法使用2d canvas保存图片，建议换成V1版本")
				}
				// #endif
			} else {
				ctx = uni.createCanvasContext(this.canvasId,this);
			}
			const scale = this.cropperRect.width / this.target.width;
			const dx = (this.cropperRect.left - this.imageRect.left) / scale;
			const dy = (this.cropperRect.top - this.imageRect.top) / scale;
			let image;
			if(this.type2d){
				image = canvas.createImage()
				image.src = this.imageSrc;
			}else{
				image = this.imageSrc;
			}
			const x = -dx,
				y = -dy,
				w = this.imageRect.width / scale,
				h = this.imageRect.height / scale;
			ctx.save();
			ctx.translate(x + w / 2, y + h / 2);
			ctx.rotate((this.rotateAngle * Math.PI) / 180);
			ctx.translate(-(x + w / 2), -(y + h / 2));
			await this.drawImage(ctx,image, x, y, w, h);
			ctx.restore();
			if (this.mask !== '') {
				let imageData;
				if (this.type2d) {
					imageData = ctx.getImageData(0, 0, this.target.width, this.target.height);
				} else {
					imageData = await new Promise(resolve => {
						uni.canvasGetImageData({
							canvasId: this.canvasId,
							x: 0,
							y: 0,
							width: this.target.width,
							height: this.target.height,
							success(res) {
								resolve(res);
							}
						},this);
					});
				}
				ctx.clearRect(0, 0, this.target.width, this.target.height);
				if(this.type2d){
					image.src = this.mask;
				}else{
					image = this.mask;
				}
				await this.drawImage(ctx,image, 0, 0, this.target.width, this.target.height);
				let maskData;
				if (this.type2d) {
					maskData = ctx.getImageData(0, 0, this.target.width, this.target.height);
				} else {
					maskData = await new Promise((resolve,reject) => {
						uni.canvasGetImageData({
							canvasId: this.canvasId,
							x: 0,
							y: 0,
							width: this.target.width,
							height: this.target.height,
							success(res) {
								resolve(res);
							}
						},this);
					});
				}
				ctx.clearRect(0, 0, this.target.width, this.target.height);
				for (let index = 3; index < maskData.data.length; index += 4) {
					const alpha = maskData.data[index];
					if (alpha !== 0) {
						imageData.data[index] = 0;
					}
				}
				if (this.type2d) {
					ctx.putImageData(imageData, 0, 0);
				} else {
					await new Promise(resolve => {
						uni.canvasPutImageData({
							canvasId: this.canvasId,
							x: 0,
							y: 0,
							width: imageData.width,
							height: imageData.height,
							data: imageData.data,
							complete: res => {
								resolve(res);
							}
						},this);
					});
				}
			}
			return new Promise((resolve,reject) => {
				const params = {};
				if (this.type2d) {
					params.canvas = canvas;
				} else {
					params.canvasId = this.canvasId;
				}

				uni.canvasToTempFilePath({
					...params,
					destWidth: this.target.width,
					destHeight: this.target.height,
					quality: Number(this.quality) || 1,
					fileType: this.fileType,
					success: ({ tempFilePath }) => {
						// #ifdef H5
						var arr = tempFilePath.split(',');
						var mime = arr[0].match(/:(.*?);/)[1];
						var bstr = atob(arr[1]);
						var n = bstr.length;
						var u8arr = new Uint8Array(n);
						for (var i = 0; i < n; i++) {
							u8arr[i] = bstr.charCodeAt(i);
						}
						var url = URL || webkitURL;
						resolve(
							url.createObjectURL(
								new Blob([u8arr], {
									type: mime
								})
							)
						);
						// #endif
						resolve(tempFilePath);
					},
					fail(err) {
						console.log('保存失败，错误信息：',err);
						reject(err);
					}
				},this);
			});
		}
	}
};
</script>
<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
<script module="wxsModule" lang="wxs">
var startTouchs = [];
var startDistance = 0;
var touchCenter = [];
var ratio = 0;
var imageInstance = null;
var cropperInstance = null;
var touchType = "";
var touchInstance = null;
var cropperRect = null;
var imageRect = null;
// 旋转角度
var rotateAngle = 0;
// 操作时改变的对象
var changes = {
	imageRect: null,
	cropperRect: null
}

function updateImageStyle() {
	var imageRect = changes.imageRect
	imageInstance.setStyle({
		left: imageRect.left + 'px',
		top: imageRect.top + 'px',
		width: imageRect.width + 'px',
		height: imageRect.height + 'px',
		transform: 'rotate(' + rotateAngle + 'deg)'
	})
}

function updateCopperStyle() {
	var cropperRect = changes.cropperRect
	cropperInstance.setStyle({
		left: cropperRect.left + "px",
		top: cropperRect.top + "px",
		width: cropperRect.width + "px",
		height: cropperRect.height + "px"
	})
}

function imageScale(scaleRate) {
	var cw = imageRect.width * (scaleRate - 1)
	var ch = imageRect.height * (scaleRate - 1)
	changes.imageRect = {
		width: imageRect.width + cw,
		height: imageRect.height + ch,
		left: imageRect.left - cw * (touchCenter[0]),
		top: imageRect.top - ch * (touchCenter[1])
	}
}
function getImageRotateSizeChange(w,h){
	var cw = h*Math.sin(rotateAngle/180 * Math.PI)
	var ch = w*Math.sin(rotateAngle/180 * Math.PI)
	return {cw,ch}
}
// 角度转弧度
function ang2deg(ang){
	return ang/180*Math.PI
}
// 计算旋转后真实的图片大小
function getRealSize(){
	var w = changes.imageRect.width
	var h = changes.imageRect.height
	var l =  changes.imageRect.left
	var t =  changes.imageRect.top
	// 内斜边
	var R = Math.sqrt(w*w+h*h)
	var angle = Math.atan(h/w) / Math.PI * 180
	var rorate = rotateAngle%90
	var direct = Math.floor(rotateAngle/90)
	var width = R*Math.cos(ang2deg(angle-rorate))
	var height = R*Math.sin(ang2deg(angle+rorate))
	if(direct % 2 === 1){
		var temp = width
		width = height
		height = temp
	}
	return {
		width: width,
		height: height,
		left: l - (width - w)/2,
		top: t - (height - h)/2,
		dw: width - w,
		dh: height - h
	}
}
module.exports = {
	touchStart: function (ev, oi) {
		// #ifdef APP-PLUS || H5
		ev.preventDefault();
		ev.stopPropagation();
		// #endif
		touchInstance = ev.instance;
		var dataSet = ev.instance.getDataset()
		touchType = dataSet.type;
		startTouchs = ev.touches;
		oi.callMethod('onTouchStart')
		if (startTouchs.length == 2) {
			touchType = "image"
			var x1 = startTouchs[0].clientX
			var y1 = startTouchs[0].clientY
			var x2 = startTouchs[1].clientX
			var y2 = startTouchs[1].clientY
			var distance = Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)
			startDistance = Math.sqrt(distance)
			var leftPercent = ((x1 + x2) / 2 - imageRect.left) / imageRect.width
			var topPercent = ((y1 + y2) / 2 - imageRect.top) / imageRect.height
			touchCenter = [leftPercent, topPercent]
		}
		return false;
	},
	touchMove: function (ev, io) {
		if (touchType == "") return false
		// #ifdef H5
		ev.preventDefault();
		ev.stopPropagation();
		// #endif
		var touches = ev.touches;
		var changeX1 = touches[0].clientX - startTouchs[0].clientX;
		var changeY1 = touches[0].clientY - startTouchs[0].clientY;
		if (startTouchs.length == 1) {
			if (touchType === 'image') {
				changes.imageRect.left = imageRect.left + changeX1;
				changes.imageRect.top = imageRect.top + changeY1;
				updateImageStyle()
			} else if (touchType === 'controller') {
				var directionX = 0;
				if (touchInstance.hasClass('left')) {
					directionX = -1;
				}
				if (touchInstance.hasClass('right')) {
					directionX = 1;
				}
				var directionY = 0;
				if (touchInstance.hasClass('top')) {
					directionY = -1
				}
				if (touchInstance.hasClass('bottom')) {
					directionY = 1
				}
				var changeX = changeX1 * directionX;
				var changeY = changeY1 * directionY;
				// 比例缩放控制
				if (ratio !== 0) {
					if (directionX * directionY !== 0) {
						if (changeX / ratio > changeY) {
							changeY = changeX / ratio
							changeX = changeY * ratio
						} else {
							changeX = changeY * ratio
							changeY = changeX / ratio
						}
					} else {
						if (directionX == 0) {
							changeX = changeY * ratio
						} else {
							changeY = changeX / ratio
						}
					}
				}
				var realSize = getRealSize()
				var width = cropperRect.width + changeX
				var height = cropperRect.height + changeY
				// var imageRight = imageRect.left + imageRect.width
				// var imageBottom = imageRect.top + imageRect.height
				var imageRight = realSize.left+realSize.width
				var imageBottom = realSize.top+realSize.height
				if (directionX != -1) {
					if (cropperRect.left + width > imageRight) {
						width = imageRight - cropperRect.left
						if (ratio !== 0) {
							height = width / ratio
						}
					}
				} else {
					var cLeft = cropperRect.left - changeX
					if (cLeft < realSize.left) {
						width = cropperRect.left + cropperRect.width - realSize.left
						if (ratio !== 0) {
							height = width / ratio
						}
					}
				}
				// 判断是否触底
				if (directionY != -1) {
					if (cropperRect.top + height > imageBottom) {
						height = imageBottom - cropperRect.top
						if (ratio !== 0) {
							width = height * ratio
						}
					}
				} else {
					var cTop = cropperRect.top - changeY
					if (cTop < realSize.top) {
						height = cropperRect.top + cropperRect.height - realSize.top
						if (ratio !== 0) {
							width = height * ratio
						}
					}
				}
				if (directionX == -1) {
					changes.cropperRect.left = cropperRect.left + cropperRect.width - width
				}
				if (directionY == -1) {
					changes.cropperRect.top = cropperRect.top + cropperRect.height - height
				}
				// 边界控制
				changes.cropperRect.width = width
				changes.cropperRect.height = height
				updateCopperStyle()
			}
		} else if (touches.length == 2 && startTouchs.length == 2) {
			var changeX2 = touches[0].clientX - touches[1].clientX;
			var changeY2 = touches[0].clientY - touches[1].clientY;
			var distance = Math.pow(changeX2, 2) + Math.pow(changeY2, 2)
			distance = Math.sqrt(distance)
			// 放大比例
			var scaleRate = distance / startDistance
			imageScale(scaleRate)
			updateImageStyle()
		}
		return false;
	},
	touchEnd: function (ev, oi) {
		if (touchType === "image") {
			var cropperLeft = cropperRect.left
			var cropperRight = cropperRect.left + cropperRect.width
			var cropperTop = cropperRect.top
			var cropperBottom = cropperTop + cropperRect.height
			var cropperRate = cropperRect.width / cropperRect.height
			var realSize = getRealSize()
			var rate = realSize.width / realSize.height
			if (realSize.width < cropperRect.width || realSize.height < cropperRect.height) {
				var scale = 1
				if (rate < cropperRate) {
					scale = cropperRect.width / realSize.width
				} else {
					scale = cropperRect.height / realSize.height
				}
				imageRect.width = changes.imageRect.width
				imageRect.height = changes.imageRect.height
				imageScale(scale)
			}
			// 边界控制start
			if (cropperLeft < realSize.left) {
				changes.imageRect.left = cropperLeft + realSize.dw/2
			}
			if (cropperRight > realSize.left + realSize.width) {
				changes.imageRect.left = cropperRight - realSize.width + realSize.dw/2
			}
			if (cropperTop < realSize.top) {
				changes.imageRect.top = cropperTop + realSize.dh/2
			}
			if (cropperBottom > realSize.top + realSize.height) {
				changes.imageRect.top = cropperBottom - realSize.height + realSize.dh/2
			}
			// 边界控制end
			updateImageStyle()
		}
		oi.callMethod('updateData', {
			cropperRect: changes.cropperRect,
			imageRect: changes.imageRect,
		})
		touchType = ""
		startTouchs = []
		return false;
	},
	// 将逻辑层的图像变换同步过来
	// 裁剪比例变化
	changeRatio: function (value) {
		ratio = value
	},
	changeRotateAngle:function (value){
		rotateAngle = value;
		if(imageInstance){
			updateImageStyle()
		}
		var realSize = getRealSize()
	},
	changeImageRect: function (value, oldValue, oi) {
		if (value) {
			imageRect = value;
			changes.imageRect = {
				left: value.left,
				top: value.top,
				width: value.width,
				height: value.height
			};
			// #ifndef MP-WEIXIN || MP-QQ
			setTimeout(function() {
				imageInstance = oi.selectComponent('.mainContent > .image')
				updateImageStyle();
			});
			// #endif
			// #ifdef MP-WEIXIN || MP-QQ
			imageInstance = oi.selectComponent('.mainContent > .image')
			updateImageStyle();
			// #endif
		}
	},
	changeCropper: function (value, oldValue, oi) {
		if (value) {
			cropperRect = value
			changes.cropperRect = {
				left: value.left,
				top: value.top,
				width: value.width,
				height: value.height
			}
			// #ifdef H5 || APP-VUE
			setTimeout(function() {
			// #endif
				cropperInstance = oi.selectComponent('.mainContent > .cropper')
				updateCopperStyle()
			// #ifdef H5 || APP-VUE
			});
			// #endif
		}
	}
}
</script>
<!-- #endif -->
<style lang="scss" scoped>
.bt-container {
	// display: flex;
	// flex-direction: column;
	// justify-content: space-between;
	height: 100%;
	box-sizing: border-box;
	// background-color: #0e1319;
	position: relative;
	overflow: hidden;

	.bt-canvas {
		position: fixed;
		left: 100%;
		top: 0;
	}

	.mainContent {
		// flex: 1;
		// flex-shrink:0;
		// margin: 60rpx;
		width: 100%;
		height: 100%;
		position: relative;
		display: flex;
		justify-content: center;
		align-items: center;
		// touch-action: none;

		.image {
			position: absolute;
			// will-change: transform;
			// transform-origin: center center;
			width: 85%;
			height: 85%;
			will-change: left, top, width, height;
		}

		.controller {
			position: absolute;
			z-index: 99;
			padding: 10rpx;
			$offset: -20rpx;

			&::after {
				display: block;
				content: '';
				filter: drop-shadow(0 0px 10rpx rgba(0, 0, 0, 0.3));
			}

			&.vertical {
				top: calc(50% - 30rpx);
			}

			&.horizon {
				left: calc(50% - 30rpx);
			}

			&.left {
				&::after {
					height: 40rpx;
					border-left: 10rpx solid #fff;
				}

				left: $offset;
			}

			&.right {
				&::after {
					height: 40rpx;
					border-right: 10rpx solid #fff;
				}

				right: $offset;
			}

			&.top {
				top: $offset;

				&::after {
					width: 40rpx;
					border-top: 10rpx solid #fff;
				}
			}

			&.bottom {
				bottom: $offset;

				&::after {
					width: 40rpx;
					border-bottom: 10rpx solid #fff;
				}
			}

			&.left.bottom,
			&.right.bottom,
			&.left.top,
			&.left.bottom {
				&::after {
					width: 30rpx;
					height: 30rpx;
					background-color: transparent;
				}
			}
		}

		.cropper {
			position: absolute;
			border: 1px solid #eee;
			box-sizing: content-box;
			// transform-origin: center center;
			outline: 999px solid rgba(0, 0, 0, 0.5);
			will-change: left, top, width, height;

			// display: contain;
			// pointer-events: none;
			.mask {
				position: absolute;
				left: 0;
				top: 0;
				width: 100%;
				height: 100%;
				opacity: 0.5;
			}

			.line {
				position: absolute;
				// background-color: #eee;
			}

			.row {
				width: 100%;
				height: 0px;
				left: 0;
				border-top: 1px dashed #007aff;
			}

			.col {
				height: 100%;
				width: 0px;
				border-left: 1px dashed #007aff;
			}

			.row1 {
				top: 33%;
			}

			.row2 {
				top: 66%;
			}

			.col1 {
				left: 33%;
			}

			.col2 {
				left: 66%;
			}
		}
	}

	// .slot {
	// 	position: relative;
	// 	padding-top: 20rpx;
	// }
}

.anim {
	transition: 0.2s;
}
</style>
